home *** CD-ROM | disk | FTP | other *** search
- #include "main.h"
- #include "patch.h"
-
- Pattern dragPat;
-
- static WindowPeek messyLevel;
- static long oldDragWindow, oldGrowWindow;
-
- /*******************************************************
- * *
- * *
- *******************************************************/
-
- defineSizeRgn( theRgn, theRect )
- Rect *theRect;
- RgnHandle theRgn;
- {
- Rect bounds, temp;
-
- OpenRgn();
- bounds = *theRect;
- SetRect( &temp, bounds.left, bounds.top - 1, bounds.right, bounds.top );
- FrameRect( &temp );
- temp.top -= 18;
- temp.bottom -= 18;
- FrameRect( &temp );
- temp.top = bounds.bottom;
- temp.bottom = bounds.bottom + 1;
- FrameRect( &temp );
- temp.top -= 15;
- temp.bottom -= 15;
- FrameRect( &temp );
- SetRect( &temp, bounds.left - 1, bounds.top - 19, bounds.left, bounds.bottom + 1 );
- FrameRect( &temp );
- temp.left = bounds.right;
- temp.right = bounds.right + 1;
- FrameRect( &temp );
- SetRect( &temp, bounds.right - 15, bounds.top, bounds.right - 14, bounds.bottom );
- FrameRect( &temp );
- CloseRgn( theRgn );
- }
-
- /*******************************************************
- * *
- * This is real ugly, but it's also real fast. It assumes the structure of the size *
- * region and updates those values that need updating. *
- * *
- *******************************************************/
-
- deltaSizeRgn( theRgn, dh, dv )
- RgnHandle theRgn;
- int dh, dv;
- {
- int *data;
-
- HLock( theRgn );
- data = *(int**)theRgn;
- data[3] = data[37] = 1 + ( data[31] += dv ); /* d', d */
- data[20] = data[34] = 1 + ( data[19] = data[33] += dh ); /* 4, 3 */
- data[27] = 1 + ( data[23] += dv ); /* c', c */
- data[4] = data[7] = data[39] = /* 6, 5 */
- 1 + ( data[11] = data[15] = data[21] = data[25] = data[29] = data[35] += dh );
- }
-
- /*******************************************************
- * *
- * This routine passes the appropriate parameters to the WDEF assocaited with *
- * theWindow, and returns the result code. This is only here as there was some *
- * difficultly casting a long to a pointer to a pascal function returning a long. *
- * It gets used when there is a click in a DA window to discover if the click was *
- * in the close box or in the drag region, so we can trap these. *
- * *
- *******************************************************/
-
- long wDefCall( defProc, varCode, theWindow, message, param )
- long defProc, theWindow;
- Rect *param;
- int varCode, message;
- {
- long result = 0;
-
- asm {
- subq.l #4,sp
- move varCode,-(sp)
- move.l theWindow,-(sp)
- move message,-(sp)
- move.l param,-(sp)
- move.l defProc, a0
- move.l (a0),a0
- jsr (a0)
- move.l (sp)+,result
- }
- return( result );
- }
-
- /*******************************************************
- * *
- * This is here mostly because of type checking problems with the compiler. *
- * *
- *******************************************************/
-
- myPinRect( theRect, thePt )
- Rect *theRect;
- Point *thePt;
- {
- if( thePt->h >= theRect->right ) thePt->h = theRect->right - 1;
- if( thePt->h < theRect->left ) thePt->h = theRect->left;
- if( thePt->v >= theRect->bottom ) thePt->v = theRect->bottom - 1;
- if( thePt->v < theRect->top ) thePt->v = theRect->top;
- }
-
- /*******************************************************
- * *
- * This emulates the DragGrayRgn routine, but does things a little differently. *
- * Instead of modifying the original region, it leaves it alone and works with a *
- * copy. It assumes that slopRect = pinRect, and assumes that there is no axis *
- * restriction. It calls actionProc with the current GrayRgn, so it knows where *
- * to mask out if it is drawing to the screen. *
- * *
- *******************************************************/
-
- setDragPat( thePat )
- Pattern *thePat;
- {
- *(long*)dragPat = *(long*)thePat;
- ((long*)dragPat)[1] = ((long*)thePat)[1];
- }
-
- long doDragTheRgn( startRgn, startPt, limitRect, slopRect, axis )
- RgnHandle startRgn;
- Point startPt;
- Rect *limitRect, *slopRect;
- int axis;
- {
- RgnHandle theRgn, oldRgn, deltaRgn, slopRgn;
- Point currPt, lastPt, pinPt;
- EventRecord theEvent;
- int offh = 0, offv = 0, outside = 0, oldOutside = 0, doPin;
- PenState savePen;
-
- slopRgn = NewRgn();
- CopyRgn( GrayRgn, slopRgn );
- InsetRgn( slopRgn, 4, 4 );
- doPin = 0; /* for now. Should actually check to make sure it is on full screen and near edges */
-
- GetPenState( &savePen );
- PenMode( notPatXor );
- PenPat( dragPat );
- theRgn = NewRgn();
- deltaRgn = NewRgn();
- oldRgn = NewRgn();
- CopyRgn( startRgn, theRgn );
- InsetRgn( theRgn, 1, 1 );
- DiffRgn( startRgn, theRgn, theRgn );
- CopyRgn( theRgn, oldRgn );
- PaintRgn( theRgn );
- lastPt = startPt;
- while( StillDown() )
- {
- GetMouse( &currPt );
- if( axis == hAxisOnly ) currPt.v = lastPt.v;
- else if( axis == vAxisOnly ) currPt.h = lastPt.h;
- pinPt = currPt;
- if( doPin && limitRect ) myPinRect( limitRect, &pinPt );
- if( !EqualPt( currPt, lastPt ))
- {
- OffsetRgn( oldRgn, offh, offv );
- OffsetRgn( theRgn, offh = pinPt.h - lastPt.h, offv = pinPt.v - lastPt.v );
- outside = !PtInRgn( currPt, slopRgn );
- if( !( outside && oldOutside ))
- {
- if( outside ) CopyRgn( oldRgn, deltaRgn );
- else if( oldOutside ) CopyRgn( theRgn, deltaRgn );
- else XorRgn( theRgn, oldRgn, deltaRgn );
- PaintRgn( deltaRgn );
- oldOutside = outside;
- }
- lastPt = currPt;
- }
- doBackground( lotsElseToDo, outside ? noGray : someGray, theRgn );
- }
- GetMouse( &currPt );
- if( !outside ) PaintRgn( theRgn );
- DisposeRgn( theRgn );
- DisposeRgn( oldRgn );
- DisposeRgn( deltaRgn );
- SetPenState( &savePen );
-
- if( PtInRgn( currPt, slopRgn ))
- SubPt( startPt, &currPt );
- else currPt.v = currPt.h = -32768;
- DisposeRgn( slopRgn );
- return( *(long*)&(currPt.v) );
- }
-
- /*******************************************************
- * *
- * *
- *******************************************************/
-
- long doGrowWindow( theWindow, startPt, bounds )
- WindowPeek theWindow;
- Point startPt;
- Rect *bounds;
- {
- EventRecord theEvent;
- GrafPtr bigPort, savePort;
- PenState savePen;
- RgnHandle saveClip, theRgn, oldRgn, deltaRgn;
- Rect sizeRect, theRect;
- Point upperLeft, currPt, lastPt, theSize, oldSize;
- long defProc, result;
- int varCode, dh, dv, oldh, oldv, offh, offv;
-
- defProc = (long)(theWindow->windowDefProc);
- varCode = ( defProc >> 24 ) & 0xf;
- defProc &= 0xffffff;
-
- GetWMgrPort( &bigPort );
- GetPort( &savePort );
- SetPort( bigPort );
- saveClip = NewRgn();
- GetClip( saveClip );
- SetClip( GrayRgn );
- GetPenState( &savePen );
- PenMode( notPatXor );
- setDragPat( gray );
- PenPat( gray );
-
- upperLeft = topLeft( theWindow->port.portBits.bounds );
- sizeRect = theWindow->port.portRect;
- OffsetRect( &sizeRect, -upperLeft.h, -upperLeft.v );
- lastPt = startPt;
- theRect = *bounds;
- OffsetRect( &theRect, sizeRect.left + startPt.h - sizeRect.right,
- sizeRect.top + startPt.v - sizeRect.bottom );
- if( theRect.right < 0 ) theRect.right = 32767;
- if( theRect.bottom < 0 ) theRect.bottom = 32767;
- theRgn = NewRgn();
- oldRgn = NewRgn();
- deltaRgn = NewRgn();
- defineSizeRgn( theRgn, &sizeRect );
- CopyRgn( theRgn, oldRgn );
- oldh = oldv = 0;
- PaintRgn( theRgn );
- while( StillDown() )
- {
- GetMouse( &currPt );
- myPinRect( &theRect, &currPt );
- dh = currPt.h - lastPt.h;
- dv = currPt.v - lastPt.v;
- if( dv || dh )
- {
- sizeRect.right += dh;
- sizeRect.bottom += dv;
- deltaSizeRgn( oldRgn, oldh, oldv );
- deltaSizeRgn( theRgn, dh, dv );
- XorRgn( theRgn, oldRgn, deltaRgn );
- PaintRgn( deltaRgn );
- oldh = dh;
- oldv = dv;
- lastPt = currPt;
- }
- doBackground( lotsElseToDo, allGray, theRgn );
- }
- GetMouse( &currPt );
- PaintRgn( theRgn );
- DisposeRgn( theRgn );
- DisposeRgn( oldRgn );
- DisposeRgn( deltaRgn );
- SetPenState( &savePen );
-
- myPinRect( &theRect, &currPt );
- theSize.h = sizeRect.right + currPt.h - lastPt.h - sizeRect.left;
- theSize.v = sizeRect.bottom + currPt.v - lastPt.v - sizeRect.top;
- oldSize = botRight( theWindow->port.portRect );
- SubPt( topLeft( theWindow->port.portRect ), &oldSize );
- if( !EqualPt( oldSize, theSize )) result = *(long*)&theSize;
- else result = 0;
-
- SetClip( saveClip );
- DisposeRgn( saveClip );
- SetPort( savePort );
- return( result );
- }
-
- /*******************************************************
- * *
- * This emulates the DragWindow routine, by calling DragGrayRgn with a copy *
- * of the strucRgn of the given window. It also passes a backgrounding routine *
- * as the actionProc. This is used instead of the DragHook global because when *
- * that was tried, it crashed. *
- * *
- *******************************************************/
-
- long doDragWindowPart( theWindow, where, bounds, front )
- WindowPeek theWindow;
- Point where;
- Rect *bounds;
- int front;
- {
- GrafPtr bigPort, savePort;
- RgnHandle saveClip;
- long offsets;
-
- GetWMgrPort( &bigPort );
- GetPort( &savePort );
- SetPort( bigPort );
- saveClip = NewRgn();
- GetClip( saveClip );
- SetClip( GrayRgn );
- if( !front ) ClipAbove( theWindow );
- messyLevel = front ? NULL : theWindow;
- setDragPat( gray );
- offsets = doDragTheRgn( theWindow->strucRgn, where, bounds, bounds, noConstraint );
- SetClip( saveClip );
- DisposeRgn( saveClip );
- SetPort( savePort );
- return( offsets );
- }
-
- doDragWindow( theWindow, where, bounds )
- WindowPeek theWindow;
- Point where;
- Rect *bounds;
- {
- PixMapPtr thePixMap;
- long offsets;
- int dv, dh, oldv, oldh, bitsLeft, bitsTop, front;
-
- if( theWindow->port.portBits.rowBytes & 0xc000 )
- {
- thePixMap = *(((CGrafPtr)theWindow)->portPixMap);
- bitsLeft = thePixMap->bounds.left;
- bitsTop = thePixMap->bounds.top;
- }
- else {
- bitsLeft = theWindow->port.portBits.bounds.left;
- bitsTop = theWindow->port.portBits.bounds.top;
- }
- front = !( getModifiers() & cmdKey );
- offsets = doDragWindowPart( theWindow, where, bounds, front );
- dv = HiWord( offsets );
- dh = LoWord( offsets );
- if(( dv != -32768 || dh != -32768 ) && ( dv != 0 || dh != 0 ))
- {
- oldh = theWindow->port.portRect.left - bitsLeft;
- oldv = theWindow->port.portRect.top - bitsTop;
- MoveWindow( theWindow, dh + oldh, dv + oldv, front );
- }
- else if( front ) SelectWindow( theWindow );
- }
-
- /*******************************************************
- * *
- * CleanWindow returns true if the given window is in front of messyLevel. This *
- * is used when the gray on the screen is from a partially-obscured drag, to *
- * detect whether there might be gray drawn on the contents of the window. *
- * *
- *******************************************************/
-
- int cleanWindow( theWindow )
- WindowPeek theWindow;
- {
- if( theWindow == messyLevel || !messyLevel ) return( 0 );
- while( theWindow = theWindow->nextWindow )
- if( theWindow == messyLevel ) return( -1 );
- return( 0 );
- }
-
- /*******************************************************
- * *
- * This is just for now - it should be easy to write one that calls the wDefProc *
- * directly and does its stuff… *
- * *
- *******************************************************/
-
- int doTrackGoAway( theWindow, where )
- WindowPtr theWindow;
- Point where;
- {
- int result;
-
- installWaitTrap();
- result = TrackGoAway( theWindow, where );
- removeWaitTrap();
- return( result );
- }
-
- /*******************************************************
- * *
- * The trap patching stuff for dragWindow, used by SystemClick in case there *
- * is a dragWindow done from a content-click. (The alarm clock does this.) *
- * *
- *******************************************************/
-
- pascal doDragTrap( theWindow, startPt, boundsRect )
- WindowPtr theWindow;
- Point startPt;
- Rect *boundsRect;
- {
- asm {
- movem.l d0-d7/a1-a5,-(sp)
- move.l CurrentA5,a5
- }
- removeWaitTrap();
- doDragWindow( theWindow, startPt, boundsRect );
- asm {
- movem.l (sp)+,d0-d7/a1-a5
- }
- }
-
- installDragWindowTrap()
- {
- oldDragWindow = NGetTrapAddress( DragWTrapNum, ToolTrap );
- NSetTrapAddress( doDragTrap, DragWTrapNum, ToolTrap );
- }
-
- removeDragWindowTrap()
- {
- NSetTrapAddress( oldDragWindow, DragWTrapNum, ToolTrap );
- }
-
- /*******************************************************
- * *
- * The trap patching stuff for growWindow, used by SystemClick stuff. *
- * *
- *******************************************************/
-
- pascal long doGrowTrap( theWindow, startPt, sizeRect )
- WindowPtr theWindow;
- Point startPt;
- Rect *sizeRect;
- {
- long result;
-
- asm {
- movem.l d0-d7/a1-a5,-(sp)
- move.l CurrentA5,a5
- }
- result = doGrowWindow( theWindow, startPt, sizeRect );
- asm {
- movem.l (sp)+,d0-d7/a1-a5
- }
- return( result );
- }
-
- installGrowTrap()
- {
- oldGrowWindow = NGetTrapAddress( GrowWTrapNum, ToolTrap );
- NSetTrapAddress( doGrowTrap, GrowWTrapNum, ToolTrap );
- }
-
- removeGrowTrap()
- {
- NSetTrapAddress( oldGrowWindow, GrowWTrapNum, ToolTrap );
- }
-
- /*******************************************************
- * *
- * This grabs some stuff before passing it along so that very little will block. *
- * Drag and GoAway are completely caught, and never passed to SystemClick. *
- * Size is special - the DA may need to adjust stuff, so I drag the size thing, *
- * without taking the mouseup event off the queue, and then call with the original *
- * mouse click point. In all other cases it is just passed directly. I tried to grab *
- * Zoom stuff, but it didn't work real well… *
- * *
- *******************************************************/
-
- doSysWindow( theEvent, theWindow )
- EventRecord *theEvent;
- WindowPeek theWindow;
- {
- long defProc, result;
- int varCode, gone;
-
- defProc = (long)(theWindow->windowDefProc);
- varCode = ( defProc >> 24 ) & 0xf;
- defProc &= 0xffffff;
- result = wDefCall( defProc, varCode, theWindow, wHit, theEvent->where );
- switch( result )
- {
- case wInDrag:
- doDragWindow( theWindow, theEvent->where, NULL );
- break;
- case wInGoAway:
- if( doTrackGoAway( theWindow, theEvent->where ))
- doClose( theWindow );
- break;
- case wInGrow:
- installGrowTrap();
- SystemClick( theEvent, theWindow );
- removeGrowTrap();
- break;
- default:
- installDelayTrap();
- installSndPatch();
- installPopUpTrap();
- installDragWindowTrap();
- installModalTrap();
- installWaitTrap();
- installAvailTrap(); /* miniDraw uses EventAvail on drawing instead of WaitMouseUp */
- SystemClick( theEvent, theWindow );
- removeAvailTrap();
- removeWaitTrap();
- removeModalTrap();
- removeDragWindowTrap();
- removePopUpTrap();
- removeSndPatch();
- removeDelayTrap();
- }
- }
-